﻿/*************************************************************************
 **项目名称： Hanbinwu.Utils   
 **项目描述：      正则表达式帮助类，提供具体的正则表达式帮助方法
 **类 名 称： RegexHelper
 **说    明： 
 **作    者： 马忠磊
 **邮    箱： 524402195@qq.com
 **微    信： mazhonglei070246
 **博    客： https://blog.csdn.net/mzl87
 **创建时间： 2019/5/11 21:48:50
 **修 改 人：        
 **修改时间：    
**************************************************************************/

namespace Hanbinwu.Utils
{
    /// <summary>
    /// 正则表达式帮助类，提供具体的正则表达式帮助方法
    /// </summary>
    public class RegexValidateHelper
    {
        #region IsEmail(是否邮箱)
        /// <summary>
        /// 邮箱验证，可以根据条件决定是否使用严格的验证模式
        /// </summary>
        /// <param name="source">邮箱地址</param>
        /// <param name="isRestrict">是否按严格模式验证</param>
        /// <returns></returns>
        public static bool IsEmail(string source, bool isRestrict = false)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            var pattern = isRestrict
                ? @"^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$"
                : @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$";

            return RegexFormatHelper.IsMatch(source, pattern);
        }
        #endregion

        #region IsMobileNumber(是否手机号码)
        /// <summary>
        /// 是否手机号码
        /// </summary>
        /// <param name="source">手机号码</param>
        /// <returns></returns>
        public static bool IsMobileNumber(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }

            /**
             * 手机号码: 
             * 13[0-9], 14[5,7], 15[0, 1, 2, 3, 5, 6, 7, 8, 9], 17[6, 7, 8], 18[0-9], 170[0-9]
             * 移动号段: 134,135,136,137,138,139,150,151,152,157,158,159,182,183,184,187,188,147,178,1705
             * 联通号段: 130,131,132,155,156,185,186,145,176,1709
             * 电信号段: 133,153,180,181,189,177,1700
             */
            return RegexFormatHelper.IsMatch(source, @"^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|70)\d{8}$");
        }
        #endregion

        #region IsTel(是否中国电话)
        /// <summary>
        /// 是否中国电话，格式：010-85849685
        /// </summary>
        /// <param name="source">电话</param>
        /// <returns></returns>
        public static bool IsTel(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^\d{3,4}-?\d{6,8}$");
        }
        #endregion

        #region IsIdCard(是否身份证号码)
        /// <summary>
        /// 是否身份证号码
        /// </summary>
        /// <param name="source">身份证</param>
        /// <returns></returns>
        public static bool IsIdCard(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            if (source.Length == 15)
            {
                return RegexFormatHelper.IsMatch(source, @"^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$");
            }
            return source.Length == 0x12 &&
                   RegexFormatHelper.IsMatch(source, @"^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$");
        }
        #endregion

        #region IsDate(是否日期)
        /// <summary>
        /// 是否日期
        /// </summary>
        /// <param name="source">日期字符串</param>
        /// <returns></returns>
        public static bool IsDate(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            //考虑到4年一度的366天，还有特殊的2月的日期
            return
                    RegexFormatHelper.IsMatch(source,
                        @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$");
        }
        #endregion

        #region IsGuid(是否Guid)
        /// <summary>
        /// 是否Guid
        /// </summary>
        /// <param name="source">Guid字符串</param>
        /// <returns></returns>
        public static bool IsGuid(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"[A-F0-9]{8}(-[A-F0-9]{4}){3}-[A-F0-9]{12}|[A-F0-9]{32}");
        }
        #endregion

        #region IsUrl(是否Url地址)
        /// <summary>
        /// 是否Url地址（统一资源定位）
        /// </summary>
        /// <param name="source">url地址</param>
        /// <returns></returns>
        public static bool IsUrl(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source,
                    @"^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{1,10}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
        }
        #endregion

        #region IsPositiveInteger(是否大于0的正整数)
        /// <summary>
        /// 是否大于0的正整数
        /// </summary>
        /// <param name="source">正整数</param>
        /// <returns></returns>
        public static bool IsPositiveInteger(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^[1-9]+\d*$");
        }
        #endregion

        #region IsInt32(是否Int32类型)
        /// <summary>
        /// 是否Int32类型
        /// </summary>
        /// <param name="source">整数</param>
        /// <returns></returns>
        public static bool IsInt32(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^[0-9]*$");
        }
        #endregion

        #region IsDouble(是否Double类型，如果带有.默认为2位0)
        /// <summary>
        /// IsDouble(是否Double类型，如果带有.默认为2位0)
        /// </summary>
        /// <param name="source">小数</param>
        /// <returns></returns>
        public static bool IsDouble(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^[0-9]+(.[0-9]{2})?$");
        }
        #endregion

        #region IsPassword(是否密码格式)
        /// <summary>
        /// 是否密码One的格式，6-25位包含特殊字符
        /// </summary>
        /// <param name="source">密码</param>
        /// <returns></returns>
        public static bool IsPasswordOne(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^[\@A-Za-z0-9\!\#\$\%\^\&\*\.\~_]{6,25}$");
        }
        /// <summary>
        /// 是否密码One的格式，指定密码长度，包含特殊字符
        /// </summary>
        /// <param name="source">密码</param>
        /// <param name="min">最小长度</param>
        /// <param name="max">最大长度</param>
        /// <returns></returns>
        public static bool IsPasswordOne(string source, int min, int max)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, string.Format(@"^[\@A-Za-z0-9\!\#\$\%\^\&\*\.\~_]{0},{1}$", "{" + min, max + "}"));
        }
        /// <summary>
        /// 是否密码Two的格式，6-25位包含特殊字符
        /// </summary>
        /// <param name="source">密码</param>
        /// <returns></returns>
        public static bool IsPasswordTwo(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return
                RegexFormatHelper.IsMatch(source,
                    @"(?=^.{6,25}$)(?=(?:.*?\d){1})(?=.*[a-z])(?=(?:.*?[A-Z]){1})(?=(?:.*?[!@#$%*()_+^&}{:;?.]){1})(?!.*\s)[0-9a-zA-Z!@#$%*()_+^&]*$");
        }
        #endregion

        #region IsLoginName(是否登录账号)
        /// <summary>
        /// 是否登录账号，6-30位长度
        /// </summary>
        /// <param name="source">登录账号</param>
        /// <returns></returns>
        public static bool IsLoginName(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^(?![^a-zA-Z]+$)[A-Za-z0-9]{6,30}$");
        }
        /// <summary>
        /// 是否登录账号
        /// </summary>
        /// <param name="source">登录账号</param>
        /// <param name="min">最小长度</param>
        /// <param name="max">最大长度</param>
        /// <returns></returns>
        public static bool IsLoginName(string source, int min, int max)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, string.Format(@"^(?![^a-zA-Z]+$)[A-Za-z0-9]{0},{1}$", "{" + min, max + "}"));
        }
        #endregion

        #region IsBankCard(是否银行卡号)
        /// <summary>
        /// 是否银行卡号，16位或19位银行卡（简单校验）
        /// </summary>
        /// <param name="source">银行卡号</param>
        /// <returns></returns>
        public static bool IsBandCard(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^(\d{16}|\d{19})$");
        }
        #endregion
        
        #region IsChinese(是否中文)
        /// <summary>
        /// 是否中文
        /// </summary>
        /// <param name="source">中文</param>
        /// <returns></returns>
        public static bool IsChinese(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^[\u4e00-\u9fa5]+$");
        }

        #endregion

        #region IsIpAddress(是否IP地址)
        /// <summary>
        /// 是否IP地址
        /// </summary>
        /// <param name="source">ip地址</param>
        /// <returns>结果</returns>
        public static bool IsIpAddress(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^(\d(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\d\.){3}\d(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\d$");
        }
        #endregion

        #region IsUnicode(是否Unicode字符串)
        /// <summary>
        /// 是否Unicode字符串
        /// </summary>
        /// <param name="source">unicode字符串</param>
        /// <returns>结果</returns>
        public static bool IsUnicode(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return
                RegexFormatHelper.IsMatch(source,
                    @"^(http|https|ftp|rtsp|mms):(\/\/|\\\\)[A-Za-z0-9%\-_@]+\.[A-Za-z0-9%\-_@]+[A-Za-z0-9\.\/=\?%\-&_~`@:\+!;]*$");
        }
        #endregion
        
        #region IsPostalCode(是否邮政编码)
        /// <summary>
        /// 是否邮政编码，6位数字
        /// </summary>
        /// <param name="source">邮政编码</param>
        /// <returns></returns>
        public static bool IsPostalCode(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            return RegexFormatHelper.IsMatch(source, @"^[1-9]\d{5}$");
        }
        #endregion

        #region IsPostfix(是否指定后缀)
        /// <summary>
        /// 是否指定后缀
        /// </summary>
        /// <param name="source">字符串</param>
        /// <param name="postfixs">后缀名数组</param>
        /// <returns></returns>
        public static bool IsPostfix(string source, string[] postfixs)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }
            string postfix = string.Join("|", postfixs);
            return RegexFormatHelper.IsMatch(source, string.Format(@".(?i:{0})$", postfix));
        }
        #endregion
    }
}
